---
type: integration
title: '@astrojs/cloudflare'
description: Aprende cómo utilizar el adaptador SSR @astrojs/cloudflare para implementar tu proyecto de Astro.
githubIntegrationURL: 'https://github.com/withastro/adapters/tree/main/packages/cloudflare'
category: adapter
i18nReady: true
---
import PackageManagerTabs from '~/components/tabs/PackageManagerTabs.astro'

Este adaptador permite a Astro desplegar tu [sitio renderizado de manera `hybrid` o `server`](/es/basics/rendering-modes/#renderizado-bajo-demanda) en [Cloudflare](https://www.cloudflare.com/).

Si estás utilizando Astro como un [constructor de sitios estáticos](/es/basics/rendering-modes/#pre-renderizado), no necesitas un adaptador.

Aprende como desplegar tu sitio en nuestra [guía de despliegue en Cloudflare Pages](/es/guides/deploy/cloudflare/).

## Por qué Astro Cloudflare

[Cloudflare](https://www.cloudflare.com/) porporciona CDNs, seguridad web y otros servicios. Este adaptador mejora el proceso de compilación de Astro para preparar tu proyecto para el despliegue a través de Cloudflare.

## Instalación

Astro incluye un comando `astro add` para automatizar la configuración de las integraciones oficiales. Si lo prefieres, puedes [instalar las integraciones manualmente](#instalación-manual) en su lugar.

Añade el adaptador de Cloudflare para habilitar SSR en tu proyecto de Astro con el comando `astro add`. Esto instalará `@astrojs/cloudflare` y realizará los cambios correspondientes en tu archivo `astro.config.mjs` en un solo paso.

<PackageManagerTabs>
  <Fragment slot="npm">
  ```sh
  npx astro add cloudflare
  ```
  </Fragment>
  <Fragment slot="pnpm">
  ```sh
  pnpm astro add cloudflare
  ```
  </Fragment>
  <Fragment slot="yarn">
  ```sh
  yarn astro add cloudflare
  ```
  </Fragment>
</PackageManagerTabs>

### Instalación manual

Primero, añade el adaptador `@astrojs/cloudflare` a las dependencias de tu proyecto utilizando tu gestor de paquetes preferido.

<PackageManagerTabs>
  <Fragment slot="npm">
  ```sh
  npm install @astrojs/cloudflare
  ```
  </Fragment>
  <Fragment slot="pnpm">
  ```sh
  pnpm add @astrojs/cloudflare
  ```
  </Fragment>
  <Fragment slot="yarn">
  ```sh
  yarn add @astrojs/cloudflare
  ```
  </Fragment>
</PackageManagerTabs>

Luego, añade el adaptador y el [modo de renderizado](/es/basics/rendering-modes/#renderizado-bajo-demanda) deseado a tu archivo `astro.config.mjs`:

```js title="astro.config.mjs" ins={2,5-6}
import { defineConfig } from 'astro/config';
import cloudflare from '@astrojs/cloudflare';

export default defineConfig({
  output: 'server',
  adapter: cloudflare(),
});
```

## Opciones

### mode

<p>
**Tipo:** `'advanced' | 'directory'`<br />
**Por defecto:** `'advanced'`
</p>

Esta opción de configuración define cómo se despliega tu proyecto de Astro en Cloudflare Pages.

* El modo `advanced` recoge el archivo `_worker.js` de la carpeta `dist`
* El modo `directory` recoge los ficheros de la carpeta `functions`, por defecto sólo se genera un fichero `[[path]].js`.

Cambiar al modo de directorio te permite añadir manualmente archivos adicionales como [plugins de Cloudflare Pages](https://developers.cloudflare.com/pages/platform/functions/plugins/), [Cloudflare Pages Middleware](https://developers.cloudflare.com/pages/platform/functions/middleware/) o funciones personalizadas utilizando [enrutamiento de funciones de Cloudflare Pages](https://developers.cloudflare.com/pages/platform/functions/routing/).

```js title="astro.config.mjs" ins="mode: 'directory'"
export default defineConfig({
  adapter: cloudflare({ mode: 'directory' }),
});
```

Para compilar un paquete separado para cada página, establece la opción `functionPerRoute` en la configuración de tu adaptador de Cloudflare. Esta opción requiere un mantenimiento manual de la carpeta `functions`. Los archivos emitidos por Astro sobrescribirán los archivos existentes con nombres idénticos en la carpeta `functions`, por lo que debes elegir nombres de archivo únicos para cada archivo que añadas manualmente. Además, el adaptador nunca vaciará la carpeta `functions` de archivos obsoletos, por lo que deberás limpiar la carpeta manualmente cuando elimines páginas.

```js title="astro.config.mjs" ins={7}
import {defineConfig} from "astro/config";
import cloudflare from '@astrojs/cloudflare';

export default defineConfig({
  adapter: cloudflare({
    mode: 'directory',
    functionPerRoute: true
  })
})
```

Este adaptador no admite el uso de [`edgeMiddleware`](/es/reference/adapter-reference/#edgemiddleware).

### routes.strategy

<p>
**Tipo:** `'auto' | 'include' | 'exclude'`<br />
**Por defecto:** `'auto'`
</p>

Determina como `routes.json` será generado si no se provee un [_routes.json](#rutas-personalizadas-_routesjson) personalizado.

Hay tres opciones disponibles:

*   **`"auto"` (por defecto):** Seleccionará automáticamente la estrategia que genere la menor cantidad de entradas. Esto debería ser casi siempre suficiente, así que elige esta opción a menos que tengas una razón específica para no hacerlo.

*   **`include`:** Las páginas y endpoints que no sean pre-renderizados se enumeran como entradas `include`, indicando a Cloudflare que invoque estas rutas como funciones. Las entradas `exclude` solo se utilizan para resolver conflictos. Por lo general, la mejor estrategia cuando tu sitio web tiene principalmente páginas estáticas y solo algunas páginas o endpoints dinámicos.

    Ejemplo: Para `src/pages/index.astro` (estático), `src/pages/company.astro` (estático), `src/pages/users/faq.astro` (estático) y `src/pages/users/[id].astro` (SSR) esto producirá el siguiente `_routes.json`:

    ```json title="dist/_routes.json"
    {
      "version": 1,
      "include": [
        "/_image", // Endpoint de imagen de Astro
        "/users/*" // Ruta dinámica
      ],
      "exclude": [
        // Las rutas estáticas que deben estar exentas de la ruta dinámica de comodín anterior
        "/users/faq/",
        "/users/faq/index.html"
      ]
    }
    ```

    **`exclude`:** Las páginas pre-renderizadas se enumeran como entradas `exclude` (indicando a Cloudflare que maneje estas rutas como activos estáticos). Por lo general, la mejor estrategia cuando tu sitio web tiene principalmente páginas o endpoints dinámicos y solo algunas páginas estáticas.

    Ejemplo: Para las mismas páginas que en el ejemplo anterior, esto producirá el siguiente `_routes.json`:

    ```json title="dist/_routes.json"
    {
      "version": 1,
      "include": [
        "/*" // Toma todo como función excepto las rutas a continuación
      ],
      "exclude": [
        // Todos los archivos estáticos
        "/",
        "/company/",
        "/index.html",
        "/users/faq/",
        "/favicon.png",
        "/company/index.html",
        "/users/faq/index.html"
      ]
    }
    ```

### routes.include

<p>
**Tipo:** `string[]`<br />
**Por defecto:** `[]`
</p>

Si quieres usar la generación automática de `_routes.json`, pero quieres incluir rutas adicionales (por ejemplo, cuando tienes funciones personalizadas en la carpeta `functions`), puedes usar la opción `routes.include` para agregar rutas adicionales al array `include`.

### routes.exclude

<p>
**Tipo:** `string[]`<br />
**Por defecto:** `[]`
</p>

Si quieres usar la generación automática de `_routes.json`, pero quieres excluir rutas adicionales, puedes usar la opción `routes.exclude` para agregar rutas adicionales al array `exclude`.

El siguiente ejemplo automáticamente genera `_routes.json` mientras incluye y excluye rutas adicionales. Ten en cuenta que esto solo es necesario si tienes funciones personalizadas en la carpeta `functions` que no son manejadas por Astro.

```js title="astro.config.mjs" ins={4-8}
export default defineConfig({
  adapter: cloudflare({
    mode: 'directory',
    routes: {
      strategy: 'include',
      include: ['/users/*'], // manejado por una función personalizada: functions/users/[id].js
      exclude: ['/users/faq'], // manejado por una página estática: pages/users/faq.astro
    },
  }),
});
```

### imageService

<p>
**Tipo:** `'passthrough' | 'cloudflare'| 'compile'`<br />
**Por defecto:** `'passthrough'`
</p>

Determina qué servicio de imágenes es utilizado por el adaptador. El adaptador utilizará el modo `passthrough` de forma predeterminada cuando se configure un servicio de imágenes incompatible. De lo contrario, utilizará el servicio de imágenes configurado globalmente:

*   **`cloudflare`:** Usa el servicio de [Redimensionamiento de Imagen de Cloudflare](https://developers.cloudflare.com/images/image-resizing/).
*   **`passthrough`:** Usa el servicio existente [`noop`](/es/guides/images/#configura-el-servicio-no-op-de-paso).
*   **`compile`:** Utiliza el servicio predeterminado de Astro (sharp), pero solo en rutas pre-renderizadas durante el tiempo de compilación. Durante el SSR para páginas renderizadas según demanda, todas las características de `astro:assets` están desactivadas.

```js title="astro.config.mjs" ins={6}
import {defineConfig} from "astro/config";
import cloudflare from '@astrojs/cloudflare';

export default defineConfig({
  adapter: cloudflare({
     imageService: 'cloudflare'
  }),
  output: 'server'
})
```

### `wasmModuleImports`

<p>
**Tipo:** `true | false`<br />
**Por defecto:** `false`
</p>

Importar o no archivos `.wasm` [directamente como módulos ES](https://github.com/WebAssembly/esm-integration/tree/main/proposals/esm-integration) usando la sintaxis de importación `.wasm?module`.

Añade `wasmModuleImports: true` a `astro.config.mjs` para habilitar esta funcionalidad tanto en la compilación de Cloudflare como en el servidor de desarrollo de Astro. Lee más sobre [el uso de módulos Wasm](#usar-módulos-wasm)

```js title="astro.config.mjs" ins={6}
import {defineConfig} from "astro/config";
import cloudflare from '@astrojs/cloudflare';

export default defineConfig({
  adapter: cloudflare({
     wasmModuleImports: true
  }),
  output: 'server'
})
```

### runtime

<p>
**Tipo:**
  ```
  { mode: 'off' }
  | { mode: 'local'; type: 'pages'; persistTo?: string; bindings?: Record<string, CF_BINDING> }
  | { mode: 'local'; type: 'workers'; persistTo?: string; };
  ```
([CF\_BINDING type reference](https://github.com/cloudflare/workers-sdk/blob/eaa16db25103d26ef31499634a31b86caccdf7aa/packages/wrangler/src/api/startDevWorker/types.ts#L190-L219))<br />
**Por defecto:** `{ mode: 'off', persistTo: '' }`
</p>

Determina si y como el Runtime de Cloudflare es añadido a `astro dev`.
Lee más sobre [el tiempo de ejecución de Cloudflare](#tiempo-de-ejecución-de-cloudflare).

La propiedad `type` define donde tu proyecto de Astro es desplegado:

*   `pages`: Desplegadas en [Cloudflare Pages](https://pages.cloudflare.com/)
*   `workers`: Desplegados en [Cloudflare Workers](https://workers.cloudflare.com/)

La propiedad `mode` define lo que quieres que el tiempo de ejecución soporte en `astro dev`:

*   `off`: no tiene acceso al tiempo de ejecución usando `astro dev`. Alternativamente, puedes usar [Vista previa con Wrangler](#vista-previa-con-wrangler) cuando necesites acceso al tiempo de ejecución, para simular el entorno de producción localmente.
*   `local`: utiliza un tiempo de ejecución local alimentado por miniflare y workerd, que soporta los Bindings de Cloudflare. Solo si quieres usar características no soportadas, como `eval`, bindings sin soporte local elige [Vista previa con Wrangler](#vista-previa-con-wrangler)

En `mode: local`, tienes acceso a la propiedad `persistTo` que define donde se guarda el estado de los bindings locales. Esto evita que se generen bindings nuevos cada vez que se reinicia el servidor de desarrollo. Este valor es un directorio relativo a la ruta de ejecución de `astro dev`. Por defecto se establece en `.wrangler/state/v3` para permitir el uso de los comandos de la interfaz de línea de comandos de `wrangler` (por ejemplo, para las migraciones). Añade esta ruta a tu `.gitignore`.

## Tiempo de ejecución de Cloudflare

El tiempo de ejecución de Cloudflare te proporciona acceso a las variables de entorno y a los bindings de Cloudflare. Puedes encontrar más información en la documentación de [Workers](https://developers.cloudflare.com/workers/configuration/bindings/) y [Pages](https://developers.cloudflare.com/pages/platform/functions/bindings/) de Cloudflare. Dependiendo de tu tipo de despliegue (`pages` o `workers`), necesitas configurar los bindings de forma diferente.

Los bindings actualmente admitidos son:

* Variables de entorno
* [Cloudflare Workers KV](https://developers.cloudflare.com/kv/)
* [Cloudflare D1](https://developers.cloudflare.com/d1/)
* [Cloudflare R2](https://developers.cloudflare.com/r2/)
* [Cloudflare Durable Objects](https://developers.cloudflare.com/durable-objects/)
* [Cloudflare Service bindings](https://developers.cloudflare.com/workers/configuration/bindings/about-service-bindings/)

### Configuración

#### Cloudflare Pages

Las Cloudflare Pages no admiten un archivo de configuración.

Para desplegar tu proyecto de páginas en producción, necesitas configurar los bindings usando el Panel de Control de Cloudflare. Para poder acceder a los bindings localmente, necesitas configurarlos usando la opción `runtime` del adaptador.

```js title="astro.config.mjs" ins={7-10, 12-15, 17-19, 21-23, 25-27, 29-32, 34-39}
import { defineConfig } from 'astro/config';
import cloudflare from '@astrojs/cloudflare';

export default defineConfig({
  output: 'server',
  adapter: cloudflare({
    runtime: {
      mode: 'local',
      type: 'pages',
      bindings: {
        // ejemplo de una variable de binding (variable de entorno)
        "URL": {
          type: "var",
          value: "https://example.com",
        },
        // ejemplo de un binding KV
        "KV": {
          type: "kv",
        },
        // ejemplo de un binding D1
        "D1": {
          type: "d1",
        },
        // ejemplo de un binding R2
        "R2": {
          type: "r2",
        },
        // ejemplo de un Durable Object binding
        "DO": {
          type: "durable-object",
          className: "DO",
        },
        // ejemplo de un binding de servicio
        "AUTH": {
          type: "service",
          address: "127.0.0.1:8787",
        }
      },
    },
  }),
});
```

Si también necesitas definir `secrets` además de las variables de entorno, necesitas añadir un archivo `.dev.vars` a la raíz del proyecto de Astro:

```ini title=".dev.vars"
DB_PASSWORD=miContraseña
```

Si quieres usar `wrangler` para los comandos de la cli, por ejemplo, las migraciones de D1, también necesitas añadir un `wrangler.toml` a la raíz del proyecto de Astro con el contenido correcto. Consulta la [documentación de Cloudflare](https://developers.cloudflare.com/) para más detalles.

```toml title="wrangler.toml"
name = "ejemplo"
compatibility_date = "2023-06-14"

# ejemplo para el binding D1
[[d1_databases]]
binding = "D1"
database_name = "D1"
database_id = "D1"
preview_database_id = "D1"
```

#### Cloudflare Workers

Para desplegar tu proyecto de workers en producción, necesitas configurar los bindings usando un archivo de configuración `wrangler.toml` en la raíz de tu proyecto de Astro. Para poder acceder a los bindings localmente, el adaptador `@astrojs/cloudflare` también leerá el archivo `wrangler.toml`.

```toml title="wrangler.toml"
name = "example"

# ejemplo de un Binding de KV
kv_namespaces = [
    { binding = "KV", id = "KV", preview_id = "KV" },
]

# ejemplo de una variable de binding (variables de entorno)
[vars]
URL = "example.com"

# ejemplo de un Binding de D1
[[d1_databases]]
binding = "D1"
database_name = "D1"
database_id = "D1"
preview_database_id = "D1"

# ejemplo de un Binding de R2
[[r2_buckets]]
binding = 'R2'
bucket_name = 'R2'

# ejemplo de un Durable Object Binding
[[durable_objects.bindings]]
name = "DO"
class_name = "DO"

# ejemplo de un Binding de Servicio
[[services]]
binding = "AUTH"
service = "auth-worker"
```

Si también necesitas definir `secrets` además de las variables de entorno, necesitas añadir un archivo `.dev.vars` a la raíz del proyecto de Astro:

```ini title=".dev.vars"
DB_PASSWORD=miContraseña
```

### Uso

Puedes acceder al runtime desde los componentes de Astro a través de `Astro.locals` dentro de cualquier archivo `.astro`.


```astro title="src/pages/index.astro"
---
const runtime = Astro.locals.runtime;
---
<pre>{JSON.stringify(runtime.env)}</pre>
```

Puedes acceder al runtime desde los endpoints de la API a través de `context.locals`:

```js title="src/pages/api/someFile.js"
export function GET(context) {
  const runtime = context.locals.runtime;

  return new Response('Algún cuerpo');
}
```

### Tipado

Si has configurado `mode: advanced`, puedes escribir el objeto `runtime` usando `AdvancedRuntime`:

```ts title="src/env.d.ts"
/// <reference types="astro/client" />

type KVNamespace = import('@cloudflare/workers-types/experimental').KVNamespace;
type ENV = {
  SERVER_URL: string;
  KV_BINDING: KVNamespace;
};

type Runtime = import('@astrojs/cloudflare').AdvancedRuntime<ENV>;

declare namespace App {
  interface Locals extends Runtime {
    user: {
      name: string;
      surname: string;
    };
  }
}
```

Si has configurado `mode: directory`, puedes escribir el objeto `runtime` usando `DirectoryRuntime`:

```ts title="src/env.d.ts"
/// <reference types="astro/client" />

type KVNamespace = import('@cloudflare/workers-types/experimental').KVNamespace;
type ENV = {
  SERVER_URL: string;
  KV_BINDING: KVNamespace;
};

type Runtime = import('@astrojs/cloudflare').DirectoryRuntime<ENV>;

declare namespace App {
  interface Locals extends Runtime {
    user: {
      name: string;
      surname: string;
    };
  }
}
```

## Plataforma

### Cabeceras

Puedes adjuntar [cabeceras personalizadas](https://developers.cloudflare.com/pages/platform/headers/) a tus respuestas añadiendo un archivo `_headers` en la carpeta `public/` de tu proyecto de Astro. Este archivo se copiará al directorio de salida de tu compilación.


### Assets

Los assets creados por Astro se nombran con un hash y, por lo tanto, se les pueden asignar encabezados de caché largos. Por defecto, Astro en Cloudflare agregará dicho encabezado para estos archivos.

### Redirecciones

Puedes declarar [redirecciones personalizadas](https://developers.cloudflare.com/pages/platform/redirects/) utilizando Cloudflare Pages. Esto te permite redirigir las peticiones a una URL diferente. Puedes añadir un archivo `_redirects` en la carpeta `public/` de tu proyecto de Astro. Este archivo se copiará en el directorio de salida de tu compilación.

## Rutas

## Importaciones de módulos Wasm

Puedes definir qué rutas invocan funciones y cuáles son assets estáticos, utilizando el [enrutamiento de Cloudflare](https://developers.cloudflare.com/pages/platform/functions/routing/#functions-invocation-routes) a través de un archivo `_routes.json`. Este archivo es generado automáticamente por Astro.

#### Rutas personalizadas `_routes.json`

Por defecto, `@astrojs/cloudflare` generará un archivo `_routes.json` con reglas `include` y `exclude` basadas en las rutas dinámicas y estáticas de tu aplicación.
Esto permitirá a Cloudflare servir archivos y procesar redirecciones estáticas sin invocar una función. La creación de un `_routes.json` personalizado anulará esta optimización automática. Consulta [la documentación de Cloudflare sobre la creación de un `routes.json` personalizado](https://developers.cloudflare.com/pages/platform/functions/routing/#create-a-_routesjson-file) para más detalles.

## Usar módulos Wasm

El siguiente es un ejemplo de importación de un módulo Wasm que luego responde a las solicitudes sumando los parámetros numéricos de la solicitud.

```js title="pages/add/[a]/[b].js"
import mod from '../util/add.wasm?module';

// crea una instancia de antes para compartir el módulo
const addModule: any = new WebAssembly.Instance(mod);

export async function GET(context) {
  const a = Number.parseInt(context.params.a);
  const b = Number.parseInt(context.params.b);
  return new Response(`${addModule.exports.add(a, b)}`);
}
```

Mientras que este ejemplo es trivial, Wasm puede ser utilizado para acelerar operaciones computacionalmente intensivas que no involucran operaciones I/O significativas, como incrustar una biblioteca de procesamiento de imágenes.

## Compatibilidad con Node.js.

De manera predeterminada, Cloudflare no soporta la API completa del tiempo de ejecución de Node.js. Sin embargo, con cierta configuración, Cloudflare sí soporta un subconjunto de las APIs del tiempo de ejecución de Node.js. Las siguientes APIs están soportadas:

*   assert
*   AsyncLocalStorage
*   Buffer
*   Crypto
*   Diagnostics Channel
*   EventEmitter
*   path
*   process
*   Streams
*   StringDecoder
*   util

Para usar estas APIs, la página o el endpoint debe ser renderizado en el lado del servidor (no pre-renderizado) y debe utilizar la sintaxis de importación `import {} from 'node:*'`.

```js title="pages/api/endpoint.js"
export const prerender = false;
import { Buffer } from 'node:buffer';
```

Además, deberás habilitar la Bandera de Compatibilidad en Cloudflare. La configuración de esta bandera puede variar según donde implementes tu sitio de Astro. Para obtener orientación detallada, consulta la [documentación de Cloudflare sobre cómo habilitar la compatibilidad con Node.js](https://developers.cloudflare.com/workers/runtime-apis/nodejs).

:::note[Implicaciones de compatibilidad de paquetes]
Si un proyecto importa un paquete en el servidor que utiliza las APIs del tiempo de ejecución de Node.js, esto puede causar problemas al implementarlo en Cloudflare. Este problema surge con paquetes que no utilizan la sintaxis de importación `node:*`. Se recomienda que te pongas en contacto con los autores del paquete para determinar si el paquete admite la sintaxis de importación mencionada anteriormente. Si el paquete no admite esto, es posible que necesites usar un paquete diferente o cambiar adaptadores.
:::

## Soporte de módulos de Cloudflare

Todos los paquetes de Cloudflare del espacio de nombres (por ejemplo, `cloudflare:sockets`) están permitidos para su uso. Ten en cuenta que el paquete `cloudflare:sockets` no funciona localmente sin utilizar el modo de desarrollo de Wrangler.

## Vista previa con Wrangler

Para utilizar [`wrangler`](https://developers.cloudflare.com/workers/wrangler/) y ejecutar tu aplicación localmente, actualiza el script de vista previa:

```json title="package.json"
"preview": "wrangler pages dev ./dist"
```

[`wrangler`](https://developers.cloudflare.com/workers/wrangler/) te proporciona acceso a [Cloudflare Bindings](https://developers.cloudflare.com/pages/platform/functions/bindings), [variables de entorno](https://developers.cloudflare.com/pages/platform/functions/bindings/#environment-variables), y al [objeto cf](https://developers.cloudflare.com/workers/runtime-apis/request/#incomingrequestcfproperties). Conseguir que la recarga en caliente o el servidor astro dev funcionen con Wrangler puede requerir una configuración personalizada. Consulta los [ejemplos de la comunidad](https://github.com/withastro/roadmap/discussions/590).

### Mensajes de error significativos

Actualmente, los errores que surjan durante la ejecución de tu aplicación en Wrangler no son muy útiles debido a la minificación de tu código. Para una mejor depuración, puedes agregar la configuración `vite.build.minify = false` a tu archivo `astro.config.mjs`.

```js title="astro.config.mjs" ins={4-8}
export default defineConfig({
  adapter: cloudflare(),
  output: 'server',
  vite: {
    build: {
      minify: false,
    },
  },
});
```

[astro-integration]: /es/guides/integrations-guide/
